home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Chans / dr2rfc / write_report.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  43.7 KB  |  1,749 lines

  1. /* write_report.c - Writes the DR struct as a Message -- */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/dr2rfc/RCS/write_report.c,v 6.0 1991/12/18 20:06:58 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Chans/dr2rfc/RCS/write_report.c,v 6.0 1991/12/18 20:06:58 jpo Rel $
  9.  *
  10.  * $Log: write_report.c,v $
  11.  * Revision 6.0  1991/12/18  20:06:58  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15.  
  16.  
  17.  
  18. /* --- *** ---
  19.  * These routines create 2 text files containing body part info:
  20.  * The files are called "hdr.822.uk" and "1.ia5". These files are
  21.  * placed by submit into the $Q/msg directory
  22.  * --- *** --- */
  23.  
  24.  
  25. #include "head.h"
  26. #include "q.h"
  27. #include "or.h"
  28. #include "dr.h"
  29. #include "tb_bpt84.h"
  30. #include <isode/cmd_srch.h>
  31. #include <isode/usr.dirent.h>
  32. #include "sys.file.h"
  33. #include <sys/stat.h>
  34.  
  35. extern CHAN        *mychan;
  36. extern CMD_TABLE        bptbl_body_parts84 [/* body part types */];
  37. extern char             *this_msg,
  38.             *loc_or,
  39.             *loc_dom,
  40.             *loc_dom_mta,
  41.             *loc_dom_site,
  42.             *postmaster,
  43.             *hdr_822_bp,
  44.             *ia5_bp,
  45.             *recip_err,
  46.             *cont_822, error[];
  47. extern Q_struct         *PPQuePtr;
  48. extern int              order_pref, linked;
  49. extern int        msgid2rfc(), reprecip2rfc(),
  50.             globalid2rfc(), x400eits2rfc(), include_admin;
  51. extern void        rfctxtfold();
  52. extern UTC        utclocalise();
  53. static int              wr_hdr_rest ();
  54. static int              get_DR ();
  55. static int        end_admin_info(), start_admin_info();
  56. static int              wr_hdr_end ();
  57. static int              wr_body ();
  58. static int              copy ();
  59. static int              DR_print ();
  60. static int              DR_write ();
  61. static DRmpdu           DRstruct;
  62. static char        *getSubject();
  63. static int        write_start(), write_cont(), write_end();
  64. static ADDR             *to;
  65. static int        linecopy();
  66. static int        do_subject_intermediate_trace();
  67. static int        get822Mailbox();
  68. static char             message[BUFSIZ*2];  /* -- holds the Recip info -- */
  69. static long        return_size;
  70. extern CMD_TABLE        rr_rcode[],
  71.             rr_dcode[],
  72.             rr_tcode[];
  73. int            forwarded;
  74.  
  75. static int        allSameType(), allSameMta();
  76.  
  77. static CMD_TABLE   rr_dcode_eng [] = {  /* -- diagnostic-codes -- */
  78.  
  79. "Unknown Address",
  80. DRD_UNRECOGNISED_OR,
  81.  
  82. "Ambiguous Address",            
  83. DRD_AMBIGUOUS_OR,
  84.  
  85. "Message rejected due to congestion",
  86. DRD_MTA_CONGESTION,
  87.  
  88. "Message looping detected (please contact local administrator)", 
  89. DRD_LOOP_DETECTED,
  90.  
  91. "Recipient's Mailbox unavailable",
  92. DRD_UA_UNAVAILABLE,
  93.  
  94. "Message timed out",
  95. DRD_MAX_TIME_EXPIRED,
  96.  
  97. "Some of your message could not be displayed by the recipient's system",
  98. DRD_ENCINFOTYPES_NOTSUPPORTED,
  99.  
  100. "The message is too big for delivery",
  101. DRD_CONTENT_TOO_LONG,
  102.  
  103. "Unable to perform the conversion required for delivery", 
  104. DRD_CONVERSION_IMPRACTICAL,
  105.  
  106. "Not allowed to perform the conversion required for delivery",
  107. DRD_CONVERSION_PROHIBITED,
  108.  
  109. "Don't know how to convert for delivery",
  110. DRD_IMPLICITCONV_NOTREGISTERED,
  111.     
  112. "One or more of the message parameters is invalid",
  113. DRD_INVALID_PARAMETERS,
  114.  
  115. "A syntax error was detected in the header of the message",
  116. DRD_CONTENT_SYNTAX_ERROR,
  117.     
  118. "X.400 protocol error - constraint violation (please contact local administrator)",
  119. DRD_SIZE_CONSTRAINT_VIOLATION,
  120.  
  121. "X.400 protocol error - missing argument (please contact local administrator)",
  122. DRD_PROTOCOL_VIOLATION,
  123.  
  124. "The recipient site could not handle the content type of the message",
  125. DRD_CONTENT_TYPE_NOT_SUPPORTED,
  126.  
  127. "The message specified too many recipients for the system to cope with",
  128. DRD_TOO_MANY_RECIPIENTS,
  129.  
  130. "Incompatibility between two sites on the route of the message (please contact local administrator)",
  131. DRD_NO_BILATERAL_AGREEMENT,
  132.     
  133. "A critical function required for the transfer or delivery of the message is not supported by the originating site of this report",
  134. DRD_UNSUPPORTED_CRITICAL_FUNCTION,
  135.     
  136. "Not allowed to perform the conversion required for delivery as it would result in loss of information",
  137. DRD_CONVERSION_WITH_LOSS_PROHIBITED,
  138.     
  139. "Some lines of the message were too long to be delivered",
  140. DRD_LINE_TOO_LONG,
  141.     
  142. "Some pages of the message were too long to be delivered",
  143. DRD_PAGE_SPLIT,
  144.  
  145. "Some pictorial symbols would have been lost if the message was delivered",
  146. DRD_PICTORIAL_SYMBOL_LOSS,
  147.  
  148. "Some punctuation symbols would have been lost if the message was delivered",
  149. DRD_PUNCTUATION_SYMBOL_LOSS,
  150.  
  151. "Some alphabetic characters would have been lost if the message was delivered",
  152. DRD_ALPHABETIC_CHARACTER_LOSS,
  153.  
  154. "Some information would have been lost if the message was delivered",
  155. DRD_MULTIPLE_INFORMATION_LOSS,
  156.  
  157. "The message could not be delivered because the originator of the message prohibited redirection",
  158. DRD_RECIPIENT_REASSIGNMENT_PROHIBITED,
  159.     
  160. "The message could not be redirected to an alternate recipient because that recipient had previously redirected the message (redirection loop)",
  161. DRD_REDIRECTION_LOOP_DETECTED,
  162.     
  163. "The message could not be delivered because the originator of the message prohibited the expansion of distribution lists",
  164. DRD_DL_EXPANSION_PROHIBITED,
  165.     
  166. "The originator of the message does not have permission to submit messages to the recipient distribution list",
  167. DRD_NO_DL_SUBMIT_PERMISSION,
  168.     
  169. "The expansion of a distribution list could not be completed",
  170. DRD_DL_EXPANSION_FAILURE,
  171.     
  172. "The postal access unit does not support the physical format required",
  173. DRD_PHYSICAL_RENDITION_ATTRIBUTES_NOT_SUPPORTED,
  174.     
  175. "The message was undeliverable because the specified recipient postal address was incorrect",
  176. DRD_UNDLIV_PD_ADDRESS_INCORRECT,
  177.     
  178. "The message was undeliverable because the physical delivery office identified by the specified postal address was incorrect or invalid",
  179. DRD_UNDLIV_PD_OFFICE_INCORRECT_OR_INVALID,
  180.  
  181. "The message was undeliverable because the specified recipient postal address was incompletely specified",
  182. DRD_UNDLIV_PD_ADDRESS_INCOMPLETE,
  183.  
  184. "The message was undeliverable because the recipient specified in the postal address was not known at that address",
  185. DRD_UNDLIV_RECIPIENT_UNKNOWN,
  186.  
  187. "The message was undeliverable because the recipient specified in the postal address is deceased",
  188. DRD_UNDLIV_RECIPIENT_DECEASED,
  189.  
  190. "The message was undeliverable because the recipient organization specified in the postal address is no longer registered",
  191. DRD_UNDLIV_ORGANIZATION_EXPIRED,
  192.  
  193. "The message was undeliverable because the recipient specified in the postal address refused to accept it",
  194. DRD_UNDLIV_RECIPIENT_REFUSED_TO_ACCEPT,
  195.  
  196. "The message was undeliverable because the recipient specified in the postal address did not collect the mail",
  197. DRD_UNDLIV_RECIPIENT_DID_NOT_CLAIM,
  198.  
  199. "The message was undeliverable because the recipient specified in the postal address had changed address permanently ('moved') and forwarding was not applicable",
  200. DRD_UNDLIV_RECIPIENT_CHANGED_ADDRESS_PERMANENTLY,
  201.  
  202. "The message was undeliverable because the recipient specified in the postal address had changed address temporarily ('on holiday') and forwarding was not applicable",
  203. DRD_UNDLIV_RECIPIENT_CHANGED_ADDRESS_TEMPORARILY,
  204.  
  205. "The message was undeliverable because the recipient specified in the postal address had changed temporary address ('departed') and forwarding was not applicable",
  206. DRD_UNDLIV_RECIPIENT_CHANGED_TEMPORARY_ADDRESS,
  207.  
  208. "The message was undeliverable because the recipient has moved and the recipient's new address is unknown",
  209. DRD_UNDLIV_NEW_ADDRESS_UNKNOWN,
  210.  
  211. "The message was undeliverable because delivery would have required physical forwarding which the recipient did not want",
  212. DRD_UNDLIV_RECIPIENT_DID_NOT_WANT_FORWARDING,
  213.  
  214. "The physical forwarding required for the message to be delivered has been prohibited by the originator of the message",
  215. DRD_UNDLIV_ORIGINATOR_PROHIBITED_FORWARDING,
  216.  
  217. "The message could not be progressed because it would violate the security policy in force",
  218. DRD_SECURE_MESSAGING_ERROR,
  219.  
  220. "The downgrading of the message's content required for delivery could not be performed",
  221. DRD_UNABLE_TO_DOWNGRADE,
  222.     0,                    -1
  223. };
  224.  
  225. int     dirlen;
  226.  
  227.  
  228. /* ---------------------  Begin  Routines  -------------------------------- */
  229.  
  230.  
  231.  
  232.  
  233. write_report (ap, DRno, recip)
  234. ADDR    *ap;
  235. int     DRno;
  236. ADDR    *recip;
  237. {
  238.     int     retval = RP_BAD;
  239.  
  240.     PP_TRACE (("write_report: %s (%d) (%s)",
  241.         ap->ad_value, DRno, this_msg));
  242.  
  243.     if (ap == NULLADDR)
  244.         return retval;
  245.     else
  246.         to = ap;
  247.  
  248.     /* -- initialise -- */
  249.     bzero (message, sizeof (message));
  250.     dr_init (&DRstruct);
  251.  
  252.     if (rp_isbad (get_DR (DRno)))
  253.         goto write_report_end;
  254.  
  255.     if (rp_isbad (wr_hdr_start()))
  256.         goto write_report_end;
  257.  
  258.     if (rp_isbad (wr_hdr_rest()))
  259.         goto write_report_end;
  260.  
  261.     if (rp_isbad (wr_hdr_end()))
  262.         goto write_report_end;
  263.  
  264.     if (rp_isbad (wr_body(ap, recip)))
  265.         goto write_report_end;
  266.  
  267.     retval = RP_OK;
  268.  
  269. write_report_end: ;
  270.     dr_free (&DRstruct);
  271.     if (recip_err) {
  272.         free(recip_err);
  273.         recip_err = NULLCP;
  274.     }
  275.     return retval;
  276.  
  277. }
  278.  
  279.  
  280.  
  281.  
  282. /*  --------------------  Static  Routines  ------------------------------- */
  283.  
  284.  
  285. static int write_p1_trace (trace)
  286. Trace    *trace;
  287. {
  288.     char    abuf[BUFSIZ];
  289.  
  290.     if (trace == NULL)
  291.         return RP_OK;
  292.     if (rp_isbad(write_p1_trace (trace -> trace_next)))
  293.         return RP_BAD;
  294.     if (x400trace2rfc (trace, abuf) == NOTOK)
  295.         return RP_BAD;
  296.     if (rp_isbad(DR_write("X400-Received: ",abuf)))
  297.         return RP_BAD;
  298.     return RP_OK;
  299. }
  300.  
  301. wr_postmaster_hdr(useDR)
  302. int    useDR;
  303. {
  304.     char    buf[BUFSIZ],
  305.         temp[BUFSIZ],
  306.         part[BUFSIZ];
  307.     RP_Buf          rps,
  308.             *rp = &rps;
  309.     UTC             now, localnow;
  310.  
  311.     PP_TRACE(("dr2rfc/wr_postmaster_hdr()"));
  312.  
  313.     if (rp_isbad (io_tpart (hdr_822_bp, FALSE, rp))) {
  314.         PP_LOG (LLOG_EXCEPTIONS,
  315.             ("dr2rfc/wr_hdr/io_tpart blows %s", rp -> rp_line));
  316.         stop_io();
  317.         (void) sprintf (error,
  318.                 "io_tpart error [%s]",
  319.                 rp -> rp_line);
  320.         return RP_BAD;
  321.     }
  322.  
  323.     if (rp_isbad (DR_write ("From: ", postmaster)))
  324.         return RP_BAD;
  325.  
  326.  
  327.     /* -- To -- */
  328.     if (useDR == TRUE && isstr(to->ad_r822DR)) {
  329.         char    *tmp;
  330.         tmp = to->ad_r822adr;
  331.         to->ad_r822adr = to->ad_r822DR;
  332.         if (adr2rfc (to, temp, order_pref) == RP_BAD)
  333.             return RP_BAD;
  334.         if (rp_isbad (DR_write ("To: ", temp)))
  335.             return RP_BAD;
  336.         to->ad_r822adr = tmp;
  337.     } else {
  338.         if (rp_isbad (DR_write ("To: ", postmaster)))
  339.             return RP_BAD;
  340.     }
  341.  
  342.     /* -- Subject -- */
  343.     if (adr2rfc (to, temp, order_pref) == RP_BAD)
  344.         return RP_BAD;
  345.  
  346.     (void) sprintf (buf, 
  347.             "Unable to send delivery report to %s",
  348.             temp);
  349.  
  350.     if (rp_isbad (DR_write ("Subject: ", buf)))
  351.         return RP_BAD;
  352.  
  353.     if (rp_isbad(DR_write("Message-Type: ", "Delivery Report")))
  354.         return RP_BAD;
  355.  
  356.     now = utcnow();
  357.     localnow = utclocalise(now);
  358.     if (UTC2rfc(localnow, buf) == NOTOK)
  359.         return RP_BAD;
  360.     if (now) free((char *) now);
  361.     if (localnow) free((char *) localnow);
  362.  
  363.     if (rp_isbad (DR_write ("Date: ", buf)))
  364.         return RP_BAD;
  365.  
  366.     if (rp_isbad (io_tdend (rp))) {
  367.         PP_LOG (LLOG_EXCEPTIONS,
  368.             ("dr2rfc/wr_hdr_end/tdend blows %s", rp -> rp_line));
  369.         (void) sprintf (error,
  370.                 "io_tdend error [%s]",
  371.                 rp -> rp_line);
  372.         stop_io();
  373.         return RP_BAD;
  374.     }
  375.     
  376.     (void) sprintf(part, "1.%s", ia5_bp);
  377.  
  378.     if (rp_isbad (io_tpart (part, FALSE, rp))) {
  379.         PP_TRACE (("dr2rfc/wr_body/tpart blows %s", rp -> rp_line));
  380.         (void) sprintf (error,
  381.                 "io_tpart error [%s]",
  382.                 rp -> rp_line);
  383.         stop_io();
  384.         return RP_BAD;
  385.     }
  386.     
  387.     if (useDR == TRUE)
  388.         (void) sprintf (buf, "The originally sender '%s' can not be reached from %s\nThe delivery report follows:\n\n",
  389.                 to->ad_value, loc_dom_site);
  390.     else
  391.         (void) sprintf(buf, "%s was unable to construct a delivery report\n\taddressed to '%s'.\nThe reason given was '%s'.\n\nThe delivery report follows:\n\n",
  392.                    mychan->ch_name,
  393.                    temp,
  394.             recip_err);
  395.     if (rp_isbad(io_tdata (buf, strlen(buf)))) {
  396.         PP_LOG  (LLOG_EXCEPTIONS, ("Error writing message"));
  397.         (void) sprintf(error,
  398.                    "io_tdata error [%s]",
  399.                    rp -> rp_line);
  400.         stop_io();
  401.         return RP_BAD;
  402.     }
  403.  
  404.     if (rp_isbad (io_tdend (rp))) {
  405.         PP_LOG (LLOG_EXCEPTIONS, ("dr2rfc/wr_body/io_tdend fails"));
  406.         (void) sprintf (error,
  407.                 "io_tdend error");
  408.         stop_io();
  409.         return RP_BAD;
  410.     }
  411.  
  412.     return RP_OK;
  413. }    
  414.     
  415. wr_hdr_start ()
  416. {
  417.     RP_Buf          rps, *rp = &rps;
  418.     char            buffer[BUFSIZ], part[BUFSIZ],
  419.     *pmailbox;
  420.     UTC             now, localnow;
  421.     Rrinfo        *ix;
  422.     if (rp_isbad (io_tinit (rp))) {
  423.         PP_LOG (LLOG_EXCEPTIONS,
  424.             ("dr2rfc/wr_hdr/tinit blows %s", rp -> rp_line));
  425.         (void) sprintf (error,
  426.                 "io_tinit error [%s]",
  427.                 rp -> rp_line);
  428.         stop_io();
  429.         return RP_BAD;
  430.     }
  431.  
  432.     if (recip_err != NULLCP) {
  433.         if (rp_isbad(wr_postmaster_hdr(FALSE)))
  434.             return RP_BAD;
  435.         (void) sprintf(part, "2.ipm/%s", hdr_822_bp);
  436.         forwarded = TRUE;
  437.     } else if  (isstr(to->ad_r822DR)) {
  438.         if (rp_isbad(wr_postmaster_hdr(TRUE)))
  439.             return RP_BAD;
  440.         (void) sprintf(part, "2.ipm/%s", hdr_822_bp);
  441.         forwarded = TRUE;
  442.     } else {
  443.         (void) sprintf(part, "%s", hdr_822_bp);
  444.         forwarded = FALSE;
  445.     }
  446.     
  447.     if (rp_isbad (io_tpart (part, FALSE, rp))) {
  448.         PP_LOG (LLOG_EXCEPTIONS,
  449.             ("dr2rfc/wr_hdr/io_tpart blows %s", rp -> rp_line));
  450.         (void) sprintf (error,
  451.                 "io_tpart error [%s]",
  452.                 rp -> rp_line);
  453.         stop_io();
  454.         return RP_BAD;
  455.     }
  456.  
  457.     if (DRstruct.dr_trace != NULL
  458.         && DRstruct.dr_trace -> trace_next != NULL)
  459.         /* not local (x400 ?) */
  460.         if (rp_isbad(write_p1_trace(DRstruct.dr_trace)))
  461.             return RP_BAD;
  462.  
  463.     /* -- From -- */
  464.     if (rp_isbad (DR_write ("From: ", postmaster)))
  465.         return RP_BAD;
  466.  
  467.  
  468.     /* -- To -- */
  469.     if (adr2rfc (to, buffer, order_pref) == RP_BAD)
  470.         return RP_BAD;
  471.     if (rp_isbad (DR_write ("To: ", buffer)))
  472.         return RP_BAD;
  473.  
  474.     /* -- Subject -- */
  475.     (void) sprintf (buffer, "Delivery Report");
  476.     
  477.     ix = DRstruct.dr_recip_list;
  478.     if (allSameType(ix, DR_REP_SUCCESS) == TRUE) 
  479.         (void) sprintf (buffer, "%s (success)", buffer);
  480.     else if (allSameType(ix, DR_REP_FAILURE) == TRUE)
  481.         (void) sprintf (buffer, "%s (failure)", buffer);
  482.     else
  483.         (void) sprintf (buffer, "%s (success and failures)", buffer);
  484.  
  485.     if (ix && ix->rr_next == NULL
  486.         && !rp_isbad(get822Mailbox(ix, &pmailbox))) {
  487.         (void) sprintf (buffer, "%s for %s", 
  488.                 buffer, pmailbox);
  489.         free(pmailbox);
  490.     } else if (allSameMta(ix, &pmailbox) == TRUE) {
  491.         (void) sprintf (buffer, "%s for MTA %s",
  492.                 buffer, pmailbox);
  493.         free(pmailbox);
  494.     }
  495.  
  496.  
  497.     if (rp_isbad (DR_write ("Subject: ", buffer)))
  498.         return RP_BAD;
  499.  
  500.     if (rp_isbad(DR_write("Message-Type: ", "Delivery Report")))
  501.         return RP_BAD;
  502.  
  503.     now = utcnow();
  504.     localnow = utclocalise(now);
  505.     if (UTC2rfc(localnow, buffer) == NOTOK)
  506.         return RP_BAD;
  507.     if (now) free((char *) now);
  508.     if (localnow) free((char *) localnow);
  509.  
  510.     if (rp_isbad (DR_write ("Date: ", buffer)))
  511.         return RP_BAD;
  512.  
  513.     return RP_OK;
  514. }
  515.  
  516.  
  517.  
  518.  
  519. static int wr_hdr_rest ()
  520. {
  521.     char            buffer [BUFSIZ],
  522.             fbuf [BUFSIZ];
  523.  
  524.     PP_TRACE (("dr2rfc/wr_hdr_rest ()"));
  525.  
  526.     /* -- P1-Message-ID -- */
  527.     if (DRstruct.dr_mpduid && DRstruct.dr_mpduid->mpduid_string) {
  528.         (void) sprintf (fbuf, "Message-ID: ");
  529.         (void) sprintf (buffer, "<\"%s\"@%s>",
  530.                 DRstruct.dr_mpduid->mpduid_string,
  531.                 loc_dom_site);
  532.         if (rp_isbad (DR_write (fbuf, buffer)))
  533.             return RP_BAD;
  534.     }
  535.  
  536.     /* -- UAContentId (optional) -- */
  537.     if (PPQuePtr -> ua_id) {
  538.         (void) sprintf (fbuf, "Content-Identifier: ");
  539.         if (rp_isbad (DR_write (fbuf, PPQuePtr -> ua_id)))
  540.             return RP_BAD;
  541.     }
  542.  
  543.     return RP_OK;
  544. }
  545.  
  546. static int get_DR (DRno)
  547. int     DRno;
  548. {
  549.     int     retval;
  550.  
  551.     PP_TRACE (("get_DR for %s (%d)", this_msg, DRno));
  552.  
  553.     retval = get_dr (DRno, this_msg, &DRstruct);
  554.     if (rp_isbad(retval) && retval != RP_EOF)
  555.         goto get_DR_free;
  556.  
  557.     return (RP_OK);
  558.  
  559. get_DR_free: ;
  560.     return RP_BAD;
  561. }
  562.  
  563.  
  564.  
  565.  
  566.  
  567. static wr_hdr_end()
  568. {
  569.     RP_Buf          rps,
  570.             *rp = &rps;
  571.  
  572.     PP_TRACE (("dr2rfc/wr_hdr_end()"));
  573.     if (rp_isbad (io_tdend (rp))) {
  574.         PP_LOG (LLOG_EXCEPTIONS,
  575.             ("dr2rfc/wr_hdr_end/tdend blows %s", rp -> rp_line));
  576.         (void) sprintf (error,
  577.                 "io_tdend error [%s]",
  578.                 rp -> rp_line);
  579.         stop_io();
  580.         return RP_BAD;
  581.     }
  582.     return RP_OK;
  583. }
  584.  
  585. extern long    max_include_msg;
  586. extern int    num_include_lines;
  587. extern int    include_all;
  588.  
  589. static wr_body (ap, recip)
  590. ADDR    *ap;
  591. ADDR    *recip;
  592. {
  593.     RP_Buf  rps,
  594.         *rp = &rps;
  595.     char    *dir = NULLCP;
  596.     char    filename[MAXPATHLENGTH],
  597.         *pmailbox, *cix, *str,
  598.         buffer[BUFSIZ],
  599.         buffer2[BUFSIZ],
  600.         part[BUFSIZ],
  601.         temp[BUFSIZ];
  602.     int     retval, avail, correlator,
  603.         nosubject = FALSE, allSuccess;
  604.     Rrinfo  *ix;
  605.     ADDR    *ad;
  606.     UTC     now;
  607.     UTC    loctime;
  608.  
  609.     if (forwarded == TRUE)
  610.         (void) sprintf(part, "2.ipm/1.%s", ia5_bp);
  611.     else
  612.         (void) sprintf(part, "1.%s", ia5_bp);
  613.  
  614.     if (rp_isbad (io_tpart (part, FALSE, rp))) {
  615.         PP_LOG(LLOG_EXCEPTIONS,
  616.                ("dr2rfc/wr_body/tpart blows %s", rp -> rp_line));
  617.         (void) sprintf (error,
  618.                 "io_tpart error [%s]",
  619.                 rp -> rp_line);
  620.         stop_io();
  621.         return RP_BAD;
  622.     }
  623.  
  624. /* dr-summary */
  625.     if (PPQuePtr -> pp_content_correlator == NULL
  626.         && PPQuePtr -> ua_id == NULL)
  627.         correlator = FALSE;
  628.     else
  629.         correlator = TRUE;
  630.  
  631.     if (correlator == TRUE) {
  632.         if (rp_isbad(write_start("This report relates to your message:", "")))
  633.             return RP_BAD;
  634.         /* content correlator */
  635.  
  636.         if (rp_isbad(pretty_output((PPQuePtr -> pp_content_correlator) ? PPQuePtr -> pp_content_correlator : PPQuePtr -> ua_id, 2)))
  637.             return RP_BAD;
  638.  
  639.     } else {
  640.         char    *subject;
  641.  
  642.         if ((subject = getSubject(this_msg, recip)) != NULLCP) {
  643.             if (rp_isbad(write_start("This report relates to your message with subject:", subject)))
  644.                 return RP_BAD;
  645.             free(subject);
  646.         } else if (rp_isbad(write_start("This report relates to your message", ""))) {
  647.             nosubject = TRUE;
  648.             return RP_BAD;
  649.         }
  650.  
  651.     }
  652.     if (DRstruct.dr_subject_intermediate_trace != NULL) {
  653.         Trace    *tix = DRstruct.dr_subject_intermediate_trace;
  654.         while (tix->trace_next != NULL)
  655.             tix = tix->trace_next;
  656.         loctime = utclocalise(tix->trace_DomSinfo.dsi_time);
  657.         if (UTC2rfc(loctime, temp) == NOTOK)
  658.             return RP_BAD;
  659.         if (loctime) free((char *) loctime);
  660.         (void) sprintf(buffer, "of %s\n",temp);
  661.         if (rp_isbad(write_cont(buffer, FALSE)))
  662.             return RP_BAD;
  663.     }
  664.     if (nosubject == TRUE 
  665.         && rp_isbad(write_cont("(no subject)", FALSE)))
  666.         return RP_BAD;
  667.  
  668.     if (rp_isbad(write_end()))
  669.         return RP_BAD;
  670.  
  671.     /* dr-recipients */
  672.     ix = DRstruct.dr_recip_list;
  673.     allSuccess = TRUE;
  674.  
  675.     while (ix != NULL) {
  676.         if (rp_isbad(get822Mailbox(ix, &pmailbox)))
  677.             return RP_BAD;
  678.         if (ix -> rr_report.rep_type == DR_REP_SUCCESS) {
  679.             if (rp_isbad(write_start("Your message was successfully delivered to", "")))
  680.                 return RP_BAD;    
  681.             if (rp_isbad(write_cont(pmailbox, FALSE)))
  682.                 return RP_BAD;
  683.             if (ix-> rr_supplementary) {
  684.                 (void) sprintf (buffer, "%s", ix -> rr_supplementary);
  685.                 if (rp_isbad(write_cont(ix -> rr_supplementary, TRUE)))
  686.                     return RP_BAD;
  687.             }
  688.  
  689.             if (ix -> rr_arrival) {
  690.                 loctime = utclocalise(ix->rr_arrival);
  691.                 if (UTC2rfc (loctime, temp) == NOTOK)
  692.                     return RP_BAD;
  693.                 if (loctime) free ((char *) loctime);
  694.                 (void) sprintf(buffer, "at %s", temp);
  695.                 if (rp_isbad(write_cont(temp, FALSE)))
  696.                     return RP_BAD;
  697.             }
  698.             if (rp_isbad(write_cont("\n", FALSE)))
  699.                 return RP_BAD;
  700.             if (rp_isbad(write_end()))
  701.                 return RP_BAD;
  702.         } else {
  703.             char    *diag;
  704.             allSuccess = FALSE;
  705.             if (rp_isbad(write_start("Your message was not delivered to ", "")))
  706.                 return RP_BAD;
  707.             if (rp_isbad(write_cont(pmailbox, FALSE)))
  708.                 return RP_BAD;
  709.             if (rp_isbad(write_cont("for the following reason:", FALSE)))
  710.                 return RP_BAD;
  711.  
  712.             if ((diag = rcmd_srch(ix -> rr_report.rep.rep_ndinfo.nd_dcode, rr_dcode_eng)) != NULL)
  713.                 (void) sprintf(buffer, "%s", diag);
  714.             else
  715.                 (void) sprintf(buffer, "%s", 
  716.                            rcmd_srch(ix -> rr_report.rep.rep_ndinfo.nd_rcode, rr_rcode));
  717.                 
  718.             if (rp_isbad(write_cont(buffer, TRUE)))
  719.                 return RP_BAD;
  720.  
  721.             if (ix-> rr_supplementary) {
  722.                 (void) sprintf (buffer, "%s", ix -> rr_supplementary);
  723.                 if (rp_isbad(write_cont(ix -> rr_supplementary, TRUE)))
  724.                     return RP_BAD;
  725.             }
  726.             if (rp_isbad(write_cont("\n", FALSE))
  727.                 || rp_isbad(write_end()))
  728.                 return RP_BAD;
  729.         }
  730.         if (pmailbox != NULLCP) {
  731.             free(pmailbox); 
  732.             pmailbox = NULLCP;
  733.             }
  734.         ix = ix -> rr_next;
  735.     }
  736.  
  737. /* dr-adminstrator-info-envelope */
  738.     if (allSuccess == FALSE
  739.         || include_admin == TRUE) {
  740.         start_admin_info();
  741.         if (DRstruct.dr_trace != NULL) {
  742.             Trace    *tix = DRstruct.dr_trace;
  743.  
  744.             if (tix -> trace_mta != NULL) {
  745.                 (void) sprintf(buffer, "by: mta %s",
  746.                            tix -> trace_mta);
  747.                 if (rp_isbad(write_start("DR generated",buffer)))
  748.                     return RP_BAD;
  749.                 if (globalid2rfc(&(tix -> trace_DomId),
  750.                          temp) == NOTOK)
  751.                     return RP_BAD;
  752.                 (void) sprintf(buffer, "in %s", temp);
  753.                 if (rp_isbad(write_cont(buffer, TRUE)))
  754.                     return RP_BAD;
  755.             } else {
  756.                 if (globalid2rfc(&(tix -> trace_DomId),
  757.                          temp) == NOTOK)
  758.                     return RP_BAD;
  759.                 (void) sprintf(buffer, "in %s", temp);
  760.                 if (rp_isbad(write_start("DR generated",buffer)))
  761.                     return RP_BAD;
  762.             }
  763.  
  764.             loctime = utclocalise (tix -> trace_DomSinfo.dsi_time);
  765.             if (UTC2rfc(loctime, temp) == NOTOK)
  766.                 return RP_BAD;
  767.             if (loctime) free((char *) loctime);
  768.  
  769.             (void) sprintf(buffer,"at %s\n*",temp);
  770.             if (rp_isbad(write_cont(buffer, FALSE))
  771.                 || rp_isbad(write_end()))
  772.                 return RP_BAD;
  773.         }
  774.  
  775.         now = utcnow();    
  776.         loctime = utclocalise(now);
  777.         if (UTC2rfc(loctime, temp) == NOTOK)
  778.             return RP_BAD;
  779.         if (now) free((char *) now);
  780.         if (loctime) free((char *) loctime);
  781.  
  782.         sprintf(buffer, "foo@%s", loc_dom_mta);
  783.         ap_s2s (buffer, &str, order_pref);
  784.         if (str != NULLCP
  785.             && (cix = index(str, '@')) != NULLCP)
  786.             (void) sprintf(buffer, "at %s", ++cix);
  787.         else
  788.             (void) sprintf(buffer, "at %s",loc_dom_mta);
  789.         if (str) free(str);
  790.  
  791.         if (rp_isbad(write_start("Converted to RFC 822",
  792.                      buffer)))
  793.             return RP_BAD;
  794.         (void) sprintf(buffer, "at %s\n*", temp);
  795.         if (rp_isbad(write_cont(buffer, FALSE))
  796.             || rp_isbad(write_end()))
  797.             return RP_BAD;
  798.  
  799.         /* dr-extra-information */
  800.         (void) sprintf(buffer, "* Delivery Report Contents:\n*\n");
  801.         if (rp_isbad(io_tdata (buffer, strlen(buffer)))) {
  802.             PP_LOG  (LLOG_EXCEPTIONS, ("Error writing message"));
  803.             (void) sprintf (error,
  804.                     "io_tdata error");
  805.                    
  806.             stop_io();
  807.             return RP_BAD;
  808.         }
  809.  
  810.         /* drc-field-list */
  811.         if (globalid2rfc(&(PPQuePtr->msgid.mpduid_DomId), buffer2) == NOTOK)
  812.             return RP_BAD;
  813.         if (PPQuePtr->msgid.mpduid_string != NULL)
  814.             (void) sprintf(buffer, "[%s;%s]",
  815.                        buffer2,
  816.                        PPQuePtr->msgid.mpduid_string);
  817.         else
  818.             (void) sprintf(buffer, "[%s]", buffer2);
  819.         if (rp_isbad (DR_write("Subject-Submission-Identifier: ",
  820.                        buffer)))
  821.             return RP_BAD;
  822.  
  823.         if (PPQuePtr -> ua_id != NULL
  824.             && rp_isbad (DR_print("Content-Identifier: ",
  825.                       PPQuePtr -> ua_id)))
  826.             return RP_BAD;
  827.  
  828.         if (PPQuePtr -> cont_type != NULL
  829.             && strcmp(PPQuePtr -> cont_type, cont_822) != 0
  830.             && rp_isbad (DR_print("Content-Type: ",
  831.                       PPQuePtr -> cont_type)))
  832.             return RP_BAD;
  833.  
  834.         if (PPQuePtr -> orig_encodedinfo.eit_types != 0) {
  835.             if (x400eits2rfc (&(PPQuePtr -> orig_encodedinfo), &buffer[0]) == NOTOK)
  836.                 return RP_BAD;
  837.             if (buffer[0] != '\0')
  838.                 if (rp_isbad
  839.                     (DR_print("Original-Encoded-Information-Types: ",
  840.                           buffer)))
  841.                     return RP_BAD;
  842.         }
  843.  
  844.         if (DRstruct.dr_subject_intermediate_trace != NULL) {
  845.             if (rp_isbad(do_subject_intermediate_trace(DRstruct.dr_subject_intermediate_trace)))
  846.                 return RP_BAD;
  847.         }
  848.  
  849.         if (DRstruct.dr_dl_history != NULL) {
  850.             DLHistory       *dlix = DRstruct.dr_dl_history;
  851.             buffer[0] = '\0';
  852.  
  853.             if (rp_isbad(write_start("Originator-and-DL-Expansion-History: ", "")))
  854.                 return RP_BAD;
  855.         
  856.             while (dlix != NULL) {
  857.                 if (dlix->dlh_next != NULL) {
  858.                     (void) sprintf(buffer, "%s,", dlix -> dlh_addr);
  859.                     if (rp_isbad(write_cont(buffer, FALSE)))
  860.                         return RP_BAD;
  861.                 } else if (rp_isbad(write_cont(dlix -> dlh_addr, FALSE)))
  862.                     return RP_BAD;
  863.                 dlix = dlix -> dlh_next;
  864.             }
  865.             if (rp_isbad(write_end()))
  866.                 return RP_BAD;
  867.         }
  868.  
  869.         if (DRstruct.dr_reporting_dl_name != NULL
  870.             && DRstruct.dr_reporting_dl_name -> fn_addr != NULL
  871.             && rp_isbad(DR_print("Reporting-DL-Name: ",
  872.                      DRstruct.dr_reporting_dl_name -> fn_addr)))
  873.             return RP_BAD;
  874.  
  875.         if (PPQuePtr -> pp_content_correlator != NULL
  876.             && (rp_isbad(write_start("Content-Correlator:", ""))
  877.             || rp_isbad(pretty_output(PPQuePtr -> pp_content_correlator,
  878.                           strlen("Content-Correlator:")))))
  879.             return RP_BAD;
  880.  
  881.         ix = DRstruct.dr_recip_list;
  882.         while (ix != NULL) {
  883.             char    *str = NULLCP;
  884.             for (ad = PPQuePtr -> Raddress; ad; ad = ad->ad_next)
  885.                 if (ad -> ad_no == ix -> rr_recip)
  886.                     break;
  887.             if (ad == NULL) {
  888.                 PP_LOG(LLOG_EXCEPTIONS,
  889.                        ("unable to find recip '%d'", ix -> rr_recip));
  890.                 return RP_BAD;
  891.             }
  892.             ap_s2s(ad -> ad_r822adr, &str, order_pref);
  893.             if (str != NULLCP) {
  894.                 (void) sprintf(buffer, "%s,", str);
  895.                 free(str);
  896.             } else
  897.                 (void) sprintf(buffer, "%s,", ad -> ad_r822adr);
  898.             if (rp_isbad(write_start("Recipient-Info:", buffer)))
  899.                 return RP_BAD;
  900.  
  901.             (void) sprintf(buffer, "%s;", ad -> ad_r400adr);
  902.             if (rp_isbad(write_cont(buffer, FALSE)))
  903.                 return RP_BAD;
  904.         
  905.             if (ix -> rr_report.rep_type == DR_REP_SUCCESS) {
  906.                 char    delivered[BUFSIZ],
  907.                 *type;
  908.                 loctime = utclocalise (ix -> rr_report.rep.rep_dinfo.del_time);
  909.                 if (UTC2rfc(loctime, delivered) == NOTOK)
  910.                     return RP_BAD;
  911.                 if (loctime) free ((char *) loctime);
  912.                 (void) sprintf(buffer, "SUCCESS delivered at %s;",
  913.                            delivered);
  914.                 if (rp_isbad(write_cont(buffer, FALSE)))
  915.                     return RP_BAD;
  916.             
  917.                 if (ix -> rr_report.rep.rep_dinfo.del_type != DRT_PUBLIC
  918.                     && (type = rcmd_srch(ix -> rr_report.rep.rep_dinfo.del_type, rr_tcode)) != NULL) {
  919.                     (void) sprintf(buffer, "type of MTS user %s (%d);",
  920.                                type,
  921.                                ix -> rr_report.rep.rep_dinfo.del_type);
  922.                     if (rp_isbad(write_cont(buffer, FALSE)))
  923.                         return RP_BAD;
  924.                 }
  925.             } else {
  926.                 char    *diag;
  927.  
  928.                 (void) sprintf(buffer, "FAILURE reason %s (%d);",
  929.                            rcmd_srch(ix -> rr_report.rep.rep_ndinfo.nd_rcode, rr_rcode),
  930.                            ix -> rr_report.rep.rep_ndinfo.nd_rcode);
  931.                 if (rp_isbad(write_cont(buffer, FALSE)))
  932.                     return RP_BAD;
  933.                 if ((diag = rcmd_srch(ix -> rr_report.rep.rep_ndinfo.nd_dcode, rr_dcode)) != NULL) {
  934.                     (void) sprintf(buffer,"diagnostic %s (%d);",
  935.                                diag,
  936.                                ix -> rr_report.rep.rep_ndinfo.nd_dcode);
  937.                     if (rp_isbad(write_cont(buffer, FALSE)))
  938.                         return RP_BAD;
  939.                 }
  940.             }
  941.  
  942.             if (DRstruct.dr_subject_intermediate_trace != NULL) {
  943.                 (void) sprintf(buffer,"last trace");
  944.                 if (PPQuePtr -> encodedinfo.eit_types != 0) {
  945.                     if(x400eits2rfc(&PPQuePtr -> encodedinfo, 
  946.                             &(temp[0])) == NOTOK)
  947.                         return RP_BAD;
  948.                     (void) sprintf(buffer,"%s (%s)", buffer, temp);
  949.                 }
  950.                 loctime = utclocalise (DRstruct.dr_subject_intermediate_trace->trace_DomSinfo.dsi_time);
  951.                 if (UTC2rfc(loctime, &temp[0]) == NOTOK)
  952.                     return RP_BAD;
  953.                 if (loctime) free ((char *) loctime);
  954.  
  955.                 (void) sprintf(buffer,"%s %s;",buffer, temp);
  956.                 if (rp_isbad(write_cont(buffer, FALSE)))
  957.                     return RP_BAD;
  958.             }
  959.  
  960.             if (ix -> rr_converted != NULL) {
  961.                 if (x400eits2rfc (ix -> rr_converted, &temp[0]) == NOTOK)
  962.                     return RP_BAD;
  963.                 if (temp[0] != '\0') {
  964.                     (void) sprintf(buffer, "converted eits %s;",
  965.                                temp);
  966.                     if (rp_isbad(write_cont(buffer, TRUE)))
  967.                         return RP_BAD;
  968.                 }
  969.             }
  970.  
  971.             if (ix -> rr_originally_intended_recip != NULL) {
  972.                 if (ix -> rr_originally_intended_recip -> fn_dn)
  973.                     (void) sprintf(buffer, "originally intended recipient %s, %s;",
  974.                                ix -> rr_originally_intended_recip -> fn_dn,
  975.                                ix -> rr_originally_intended_recip -> fn_addr);
  976.                 else
  977.                     (void) sprintf(buffer, "originally intended recipient %s;",
  978.                                ix -> rr_originally_intended_recip -> fn_addr);
  979.  
  980.                 if (rp_isbad(write_cont(buffer, TRUE)))
  981.                     return RP_BAD;
  982.             }
  983.         
  984.             if (ix -> rr_supplementary != NULL) {
  985.                 (void) sprintf(buffer, "supplementary info \"%s\";",
  986.                            ix -> rr_supplementary);
  987.                 if (rp_isbad(write_cont(buffer, TRUE)))
  988.                     return RP_BAD;
  989.             }
  990.         
  991.             if (ix -> rr_redirect_history != NULL) {
  992.                 Redirection     *rix = ix -> rr_redirect_history;
  993.                 temp[0] = '\0';
  994.                 if (rp_isbad(write_cont("redirection history", FALSE)))
  995.                     return RP_BAD;
  996.                 while (rix != NULL) {
  997.                     if (rix -> rd_next != NULL) 
  998.                         (void) sprintf(buffer, "%s,", rix -> rd_addr);
  999.                     else
  1000.                         (void) sprintf(buffer, "%s;", rix -> rd_addr);
  1001.                     if (rp_isbad(write_cont(buffer, TRUE)))
  1002.                         return RP_BAD;
  1003.                     rix = rix -> rd_next;
  1004.                 }
  1005.             }
  1006.  
  1007.             if (ix -> rr_physical_fwd_addr != NULL) {
  1008.                 (void) sprintf(buffer, "physical forwarding address %s;",
  1009.                            ix -> rr_physical_fwd_addr -> fn_addr);
  1010.                 if (rp_isbad(write_cont(buffer, FALSE)))
  1011.                     return RP_BAD;
  1012.             }
  1013.             if (rp_isbad(write_end()))
  1014.                 return RP_BAD;
  1015.             ix = ix -> rr_next;
  1016.         }
  1017.         end_admin_info();
  1018.     }
  1019.  
  1020.     /* dr-content-return */
  1021.  
  1022.     avail = FALSE;
  1023.     if (allSuccess != TRUE &&
  1024.         PPQuePtr -> content_return_request == TRUE) {
  1025.         if (qid2dir (this_msg, PPQuePtr->Oaddress, TRUE, &dir) == NOTOK) {
  1026.             PP_LOG(LLOG_EXCEPTIONS, ("qid2dir failed for originator"));
  1027.             dir = NULLCP;
  1028.         } else if (msg_rinit(dir) == NOTOK)
  1029.             PP_LOG(LLOG_EXCEPTIONS, ("msg_rinit failed"));
  1030.         else if ((retval = msg_rfile (filename)) == RP_OK) {
  1031.             /* check for correct content type i.e presence of hdr.822 */
  1032.             if ((cix = rindex(filename, '/')) == NULLCP)
  1033.                 cix = filename;
  1034.             else
  1035.                 cix++;
  1036.             
  1037.             if (strncmp(cix, 
  1038.                     hdr_822_bp, 
  1039.                     strlen(hdr_822_bp)) != 0)  {
  1040.                 PP_LOG(LLOG_DEBUG, 
  1041.                        ("Unable to find a hdr.822 in directory '%s'", dir));
  1042.                 (void) msg_rend();
  1043.             } else
  1044.                 avail = TRUE;
  1045.         } else 
  1046.             (void) msg_rend();
  1047.     }
  1048.  
  1049.     if (TRUE == allSuccess) 
  1050.         (void) sprintf(buffer,
  1051.                    "\nThe Original Message is not returned with positive reports\n");
  1052.     else if (avail == TRUE) {
  1053.         dirlen = strlen(dir) + 1;
  1054.         if (include_all == TRUE
  1055.             || PPQuePtr -> msgsize <= max_include_msg)
  1056.             (void) sprintf(buffer, "\nThe Original Message follows:\n\n");
  1057.         else
  1058.             (void) sprintf(buffer, "\nThe Original Message follows but for size reasons has been truncated:\n\n");
  1059.     } else 
  1060.         (void) sprintf(buffer, "\nThe Original Message is not available\n");
  1061.  
  1062.     if (avail == FALSE || allSuccess == TRUE) {
  1063.         if (rp_isbad(io_tdata (buffer, strlen(buffer)))) {
  1064.             PP_LOG  (LLOG_EXCEPTIONS, ("Error writing message"));
  1065.             (void) sprintf(error,
  1066.                        "io_tdata error");
  1067.             stop_io();
  1068.             return RP_BAD;
  1069.         }
  1070.     }
  1071.  
  1072.     if (rp_isbad (io_tdend (rp))) {
  1073.         PP_LOG (LLOG_EXCEPTIONS, ("dr2rfc/wr_body/io_tdend fails"));
  1074.         (void) sprintf(error,
  1075.                    "io_tdend error");
  1076.         stop_io();
  1077.         return RP_BAD;
  1078.     }
  1079.  
  1080.     if (avail == FALSE || allSuccess == TRUE) {
  1081.         if (rp_isbad (io_tend (rp))) {
  1082.             PP_LOG (LLOG_EXCEPTIONS, ("dr2rfc/wr_body/io_tend fails"));
  1083.             (void) sprintf(error,
  1084.                        "io_tend error");
  1085.             stop_io();
  1086.             return RP_BAD;
  1087.         } else
  1088.             return RP_OK;
  1089.     }
  1090.  
  1091.     return_size = 0;
  1092.  
  1093.     /* copy header no matter what size */
  1094.     if (rp_isbad (retval = copy (filename)))  {
  1095.         PP_LOG (LLOG_EXCEPTIONS, ("failed to copy header '%s'", filename));
  1096.            (void) sprintf (error,
  1097.                    "Failed to submit header '%s'",
  1098.                    filename);
  1099.         return RP_BAD;
  1100.     }     
  1101.  
  1102.     if (allSuccess == FALSE) {
  1103.         if (include_all == TRUE
  1104.             || PPQuePtr -> msgsize <= max_include_msg) 
  1105.             while ((retval = msg_rfile (filename)) == RP_OK) {
  1106.                 if (rp_isbad (retval = copy (filename)))
  1107.                     break;
  1108.             }
  1109.         else {
  1110.             int numLines = 0;
  1111.             while ((retval = msg_rfile (filename)) == RP_OK
  1112.                    && numLines < num_include_lines
  1113.                    && return_size < max_include_msg) {
  1114.                 if (rp_isbad (retval = linecopy (filename, &numLines)))
  1115.                     break;
  1116.             }
  1117.         }
  1118.     }
  1119.     if (dir) free(dir);
  1120.  
  1121.     if (rp_isbad (retval)) {
  1122.         PP_LOG (LLOG_EXCEPTIONS, ("message copy failed"));
  1123.         return RP_BAD;
  1124.     }
  1125.  
  1126.     if (rp_isbad (retval = msg_rend ())) {
  1127.         PP_LOG (LLOG_EXCEPTIONS, ("msg_rend () failed"));
  1128.         (void) sprintf (error,
  1129.                 "msg_rend failed");
  1130.         return RP_BAD;
  1131.     }
  1132.  
  1133.     if (rp_isbad (io_tend (rp))) {
  1134.         PP_LOG (LLOG_EXCEPTIONS, ("dr2rfc/wr_body/io_tend fails"));
  1135.         (void) sprintf (error,
  1136.                 "io_tend failed");
  1137.         stop_io();
  1138.         return RP_BAD;
  1139.     }
  1140.  
  1141.     return RP_OK;
  1142. }
  1143.  
  1144. static int do_subject_intermediate_trace(trace)
  1145. Trace    *trace;
  1146. {
  1147.     char    *j, oldj, buffer[BUFSIZ];
  1148.     if (trace->trace_next != NULL
  1149.         && rp_isbad(do_subject_intermediate_trace(trace->trace_next)))
  1150.         return RP_BAD;
  1151.         
  1152.     if (trace2rfc(trace, buffer) == NOTOK)
  1153.         return RP_BAD;
  1154.  
  1155.     j = buffer;
  1156.     while (*j != '\0' && *j != ';') j++;
  1157.     if (*j != '\0') j++;
  1158.     oldj = *j;
  1159.     *j = '\0';
  1160.     if (rp_isbad(write_start("Subject-Intermediate-Trace-Information: ", buffer)))
  1161.         return RP_BAD;
  1162.     if (oldj != '\0') {
  1163.         *j = oldj;
  1164.         if (rp_isbad(write_cont(j,FALSE)))
  1165.             return RP_BAD;
  1166.     }
  1167.     if (rp_isbad(write_end()))
  1168.         return RP_BAD;
  1169.     return RP_OK;
  1170. }
  1171.  
  1172. static int linecopy (file, pnumlines)
  1173. char    *file;
  1174. int    *pnumlines;
  1175. {
  1176.     FILE    *fp;
  1177.     RP_Buf  rps,
  1178.         *rp = &rps;
  1179.     int     retval = RP_OK;
  1180.     char    buf[BUFSIZ], *ix, *top;
  1181.  
  1182.     ix = strdup(file + dirlen);
  1183.  
  1184.     /* strip of following -us or -uk from hdr_822_bp's */
  1185.     if ((top = rindex(ix, '/')) == NULLCP)
  1186.         top = ix;
  1187.     else
  1188.         top++;
  1189.  
  1190.     if (lexnequ(top, hdr_822_bp, strlen(hdr_822_bp)) == 0) 
  1191.         *(top+strlen(hdr_822_bp)) = '\0';
  1192.  
  1193.     if (forwarded == TRUE)
  1194.         (void) sprintf(buf, "2.ipm/2.ipm/%s", ix);
  1195.     else
  1196.         (void) sprintf(buf, "2.ipm/%s", ix);
  1197.  
  1198.     free(ix);
  1199.  
  1200.     if (rp_isbad(io_tpart (buf, FALSE, rp))) {
  1201.         PP_TRACE (("dr2rfc/wr_body/tpart blows %s", rp -> rp_line));
  1202.         stop_io();
  1203.         return RP_BAD;
  1204.     }
  1205.  
  1206.     if ((fp = fopen (file, "r")) == NULL) {
  1207.         PP_SLOG (LLOG_EXCEPTIONS, file,
  1208.               ("Can't open file"));
  1209.         (void) sprintf (error,
  1210.                 "Can't open file '%s'",
  1211.                 file);
  1212.         stop_io();
  1213.         return RP_FOPN;
  1214.     }
  1215.  
  1216.     while (*pnumlines < num_include_lines
  1217.            && return_size < max_include_msg
  1218.            && fgets (buf, sizeof buf, fp) != NULL) {
  1219.         if (io_tdata (buf, strlen(buf)) != RP_OK) {
  1220.             PP_LOG (LLOG_EXCEPTIONS, ("io_tdata error"));
  1221.             (void) sprintf (error,
  1222.                     "io_tdata error");
  1223.             stop_io();
  1224.             retval = RP_FIO;
  1225.             break;
  1226.         }
  1227.         (*pnumlines)++;
  1228.         return_size += strlen(buf);
  1229.     }
  1230.     
  1231.     if (*pnumlines >= num_include_lines
  1232.         || return_size >= max_include_msg) {
  1233.         if (io_tdata("......(message truncated)\n",
  1234.                  strlen("......(message truncated)\n")) != RP_OK) {
  1235.             PP_LOG (LLOG_EXCEPTIONS, ("io_tdata error"));
  1236.             (void) sprintf (error,
  1237.                     "io_tdata error");
  1238.             stop_io();
  1239.             retval = RP_FIO;
  1240.         }
  1241.     }
  1242.         
  1243.     (void) fclose (fp);
  1244.     if (rp_isbad (io_tdend (rp))) {
  1245.         PP_LOG (LLOG_EXCEPTIONS, ("dr2rfc/wr_body/io_tdend fails"));
  1246.         (void) sprintf (error,
  1247.                 "io_tdend fails");
  1248.         stop_io();
  1249.         return RP_BAD;
  1250.     }
  1251.     return retval;
  1252. }
  1253.  
  1254. static int copy (file)
  1255. char    *file;
  1256. {
  1257.     FILE    *fp;
  1258.     RP_Buf  rps,
  1259.         *rp = &rps;
  1260.     int     retval = RP_OK;
  1261.     extern char    *hdr_822_bp;
  1262.     char    buf[BUFSIZ], *ix, *top;
  1263.     int     n;
  1264.     struct stat st;
  1265.  
  1266.     ix = strdup(file + dirlen);
  1267.  
  1268.     /* strip of following -us or -uk from hdr_822_bp's */
  1269.     if ((top = rindex(ix, '/')) == NULLCP)
  1270.         top = ix;
  1271.     else
  1272.         top++;
  1273.  
  1274.     if (lexnequ(top, hdr_822_bp, strlen(hdr_822_bp)) == 0) 
  1275.         *(top+strlen(hdr_822_bp)) = '\0';
  1276.  
  1277.     if (stat(file, &st) != 0) {
  1278.         PP_SLOG(LLOG_EXCEPTIONS, file,
  1279.             ("Can't open file"));
  1280.         return RP_BAD;
  1281.     }
  1282.     
  1283.     if (linked == TRUE) {
  1284.         if (forwarded == TRUE)
  1285.             (void) sprintf(buf, "2.ipm/2.ipm/%s %s", ix, file);
  1286.         else
  1287.             (void) sprintf(buf, "2.ipm/%s %s", ix, file);
  1288.         free(ix);
  1289.         if (rp_isbad(io_tpart (buf, TRUE, rp))) {
  1290.             PP_LOG(LLOG_EXCEPTIONS,
  1291.                    ("dr2rfc/wr_body/tpart blows %s", rp -> rp_line));
  1292.             stop_io();
  1293.             return RP_BAD;
  1294.         }
  1295.     } else {
  1296.         if (forwarded == TRUE)
  1297.             (void) sprintf(buf, "2.ipm/2.ipm/%s", ix);
  1298.         else
  1299.             (void) sprintf(buf, "2.ipm/%s", ix);
  1300.         free(ix);
  1301.         if (rp_isbad(io_tpart (buf, FALSE, rp))) {
  1302.             PP_LOG(LLOG_EXCEPTIONS,
  1303.                    ("dr2rfc/wr_body/tpart blows %s", rp -> rp_line));
  1304.             stop_io();
  1305.             return RP_BAD;
  1306.         }
  1307.  
  1308.         if ((fp = fopen (file, "r")) == NULL) {
  1309.             PP_SLOG (LLOG_EXCEPTIONS, file,
  1310.                  ("Can't open file"));
  1311.             (void) sprintf (error,
  1312.                     "Can't open file '%s'",
  1313.                     file);
  1314.             stop_io();
  1315.             return RP_FOPN;
  1316.         }
  1317.  
  1318.         while ((n = fread (buf, sizeof (char), sizeof buf, fp)) > 0) {
  1319.             if (io_tdata (buf, n) != RP_OK) {
  1320.                 PP_LOG (LLOG_EXCEPTIONS, ("io_tdata error"));
  1321.                 (void) sprintf(error,
  1322.                            "io_tdata error");
  1323.                 stop_io();
  1324.                 retval = RP_FIO;
  1325.                 break;
  1326.             }
  1327.         }
  1328.         (void) fclose (fp);
  1329.         if (rp_isbad (io_tdend (rp))) {
  1330.             PP_LOG (LLOG_EXCEPTIONS, ("dr2rfc/wr_body/io_tdend fails"));
  1331.             (void) sprintf(error,
  1332.                        "io_tdend fails");
  1333.             stop_io();
  1334.             return RP_BAD;
  1335.         }
  1336.     }
  1337.  
  1338.     return_size += (long) st.st_size;
  1339.     return retval;
  1340. }
  1341.  
  1342. #define    DEFAULT_FOLD_LENGTH    70
  1343.  
  1344. int    chnum, tab = 8, foldlength = DEFAULT_FOLD_LENGTH;
  1345. static    int    admin_info = FALSE;
  1346.  
  1347. static int start_admin_info ()
  1348. {
  1349.     write_start ("***** The following information is directed towards the local administrator\n***** and is not intended for the end user\n*", "");
  1350.     write_end ();
  1351.     admin_info = TRUE;
  1352. }
  1353.  
  1354. static int end_admin_info()
  1355. {
  1356.     admin_info = FALSE;
  1357.     write_start("****** End of administration information", "");
  1358.     write_end();
  1359. }
  1360.  
  1361. static int write_start(key, value)
  1362. char    *key,
  1363.     *value;
  1364. {
  1365.     int    retval;
  1366.     char    buffer[BUFSIZ];
  1367.     if (key == NULLCP) {
  1368.         PP_LOG(LLOG_EXCEPTIONS, ("Null key in output"));
  1369.         return RP_BAD;
  1370.     }
  1371.  
  1372.     (void) sprintf(buffer, "%s%s %s", 
  1373.                (admin_info == TRUE) ? "* " : "",
  1374.                key, value);
  1375.     if (rp_isbad(retval = io_tdata(buffer, strlen(buffer)))) {
  1376.         PP_LOG(LLOG_EXCEPTIONS, ("io_tdata error"));
  1377.         (void) sprintf(error,
  1378.                    "io_tdata error");
  1379.         stop_io();
  1380.     }
  1381.     chnum = strlen(buffer);
  1382.  
  1383.     return retval;
  1384. }
  1385.  
  1386. static int write_cont(value, fold)
  1387. char    *value;
  1388. int    fold;
  1389. {
  1390.     int    retval, len;
  1391.     char    buffer[BUFSIZ], *ix, *base, *lastix, *foldpt, savech;
  1392.     
  1393.     if (value == NULLCP) {
  1394.         PP_LOG(LLOG_EXCEPTIONS, ("Null value in output"));
  1395.         return RP_BAD;
  1396.     }
  1397.     
  1398.     len = strlen(value);
  1399.     
  1400.     bzero(buffer, sizeof buffer);
  1401.     
  1402.     if (fold == FALSE) {
  1403.         if (chnum + len > foldlength) {
  1404.             (void) sprintf(buffer, "\n%s%*s%s", 
  1405.                        (admin_info == TRUE) ? "* ": "",
  1406.                        tab, "", value);
  1407.             chnum = tab;
  1408.         } else
  1409.             (void) sprintf(buffer, " %s", value);
  1410.         chnum += len;
  1411.     } else {
  1412.         ix = lastix = base = value;
  1413.  
  1414.         /* write_cont assume big start new line */
  1415.         (void) sprintf (buffer, "\n%s%*s",
  1416.                 (admin_info == TRUE) ? "* " : "",
  1417.                 tab, "");
  1418.         chnum = tab;
  1419.  
  1420.         while (ix != NULLCP && *ix != '\0') {
  1421.             while (*ix != '\0' && !isspace(*ix)) 
  1422.                 ix++;
  1423.  
  1424.             if (chnum + (ix - base) > foldlength) {
  1425.                 /* need to fold */
  1426.                 if (lastix == base)
  1427.                     foldpt = ix;
  1428.                 else
  1429.                     foldpt = lastix;
  1430.                 savech = *foldpt;
  1431.                 *foldpt = '\0';
  1432.                 (void) sprintf (buffer, "%s%s\n%s%*s",
  1433.                         buffer, base,
  1434.                         (admin_info == TRUE) ? "* " : "",
  1435.                         tab, "");
  1436.                 *foldpt = savech;
  1437.                 base = foldpt;
  1438.                 if (savech != '\0')
  1439.                     /* skip last space */
  1440.                     base++;
  1441.                 chnum = tab;
  1442.             }
  1443.             lastix = ix;
  1444.             if (*ix != '\0') ix++;
  1445.         }
  1446.         /* flush rest */
  1447.         if (base != ix) {
  1448.             if (chnum + (ix - base) > foldlength) {
  1449.                 (void) sprintf(buffer, "%s\n%s%*s%s",
  1450.                            buffer,
  1451.                            (admin_info == TRUE) ? "* " : "",
  1452.                            tab, "", base);
  1453.                 chnum = tab;
  1454.             } else 
  1455.                 (void) strcat (buffer, base);
  1456.             chnum += ix - base;
  1457.         }
  1458.     }
  1459.  
  1460.     if (rp_isbad(retval = io_tdata(buffer, strlen(buffer)))) {
  1461.         PP_LOG(LLOG_EXCEPTIONS, ("io_tdata error"));
  1462.         (void) sprintf(error,
  1463.                    "io_tdata error");
  1464.         stop_io();
  1465.     }
  1466.     return retval;
  1467. }
  1468.  
  1469. static int write_end()
  1470. {
  1471.     int retval;
  1472.     if (rp_isbad(retval = io_tdata("\n", strlen("\n")))) {
  1473.         PP_LOG(LLOG_EXCEPTIONS, ("io_tdata error"));
  1474.         (void) sprintf(error,
  1475.                    "io_tdata error");
  1476.         stop_io();
  1477.     }
  1478.     return retval;
  1479. }
  1480.  
  1481. static int DR_write (key, value)
  1482. char    *key;
  1483. char    *value;
  1484. {
  1485.     char    buffer[BUFSIZ];
  1486.     int     retval;
  1487.  
  1488.     if (value == NULLCP) {
  1489.         PP_LOG (LLOG_EXCEPTIONS, ("No value for key %s", key));
  1490.         return RP_BAD;
  1491.     }
  1492.  
  1493.     bzero (buffer, sizeof buffer);
  1494.     if (admin_info == TRUE)
  1495.         (void) strcat (buffer, "* ");
  1496.     if (key)
  1497.         (void) strcat (buffer, key);
  1498.     (void) strcat (buffer, value);
  1499.     (void) strcat (buffer, "\n");
  1500.     if (rp_isbad (retval = io_tdata (buffer, strlen (buffer)))) {
  1501.         PP_LOG (LLOG_EXCEPTIONS, ("io_tdata error"));
  1502.         (void) sprintf (error,
  1503.                 "io_tdata error");
  1504.         stop_io();
  1505.     }
  1506.     return retval;
  1507. }
  1508.  
  1509.  
  1510. static int DR_print (key, value)
  1511. char    *key;
  1512. char    *value;
  1513. {
  1514.     char    buffer [BUFSIZ];
  1515.     char    obuf[BUFSIZ];
  1516.     int     retval;
  1517.  
  1518.     if (value == NULLCP) {
  1519.         PP_LOG (LLOG_EXCEPTIONS, ("No value for key %s", key));
  1520.         return RP_BAD;
  1521.     }
  1522.  
  1523.     bzero (buffer, sizeof buffer);
  1524.     if (admin_info == TRUE)
  1525.         (void) strcat (buffer, "* ");
  1526.     if (key)
  1527.         (void) strcat (buffer, key);
  1528.     (void) strcat (buffer, value);
  1529.     rfctxtfold (buffer, obuf, 66);
  1530.     if (rp_isbad (retval = io_tdata (obuf, strlen (obuf)))) {
  1531.         PP_LOG (LLOG_EXCEPTIONS, ("io_tdata error"));
  1532.         (void) sprintf (error,
  1533.                 "io_tdata error");
  1534.         stop_io();
  1535.     }
  1536.     return retval;
  1537. }
  1538.  
  1539. /* output string padding newlines with some indentation */
  1540.  
  1541. pretty_output(str, padding)
  1542. char    *str;
  1543. int    padding;
  1544. {
  1545.     char    buffer[BUFSIZ];
  1546.     int     i = 0, ix;
  1547.     if (str == NULL)
  1548.         return RP_BAD;
  1549.  
  1550.     while (*str != '\0') {
  1551.         if (i == BUFSIZ-1) {
  1552.             /* flush buffer */
  1553.             buffer[i] = '\0';
  1554.             if (rp_isbad(io_tdata(buffer, strlen(buffer)))) {
  1555.                 PP_LOG  (LLOG_EXCEPTIONS, ("Error writing message"));
  1556.                 (void) sprintf (error,
  1557.                         "io_tdata error");
  1558.                 stop_io();
  1559.                 return RP_BAD;
  1560.             }
  1561.             i = 0;
  1562.         }
  1563.  
  1564.         buffer[i++] = *str;
  1565.  
  1566.         if (*str++ == '\n') {
  1567.             if (i >= BUFSIZ - 3) {
  1568.                 /* flush buffer */
  1569.                 buffer[i] = '\0';
  1570.                 if (rp_isbad(io_tdata(buffer, strlen(buffer)))) {
  1571.                     PP_LOG  (LLOG_EXCEPTIONS, ("Error writing message"));
  1572.                     (void) sprintf (error,
  1573.                             "io_tdata error");
  1574.                     stop_io();
  1575.                     return RP_BAD;
  1576.                 }
  1577.                 i = 0;
  1578.             }
  1579.  
  1580.             if (admin_info == TRUE)
  1581.                 buffer[i++] = '*';
  1582.  
  1583.             /* pad newlines */
  1584.             for (ix = 0; ix < padding; ix++)
  1585.                 buffer[i++] = ' ';
  1586.         }
  1587.  
  1588.     }
  1589.  
  1590.     if (i > 0) {
  1591.         /* flush buffer */
  1592.         buffer[i] = '\0';
  1593.         if (rp_isbad(io_tdata(buffer, strlen(buffer)))) {
  1594.             PP_LOG  (LLOG_EXCEPTIONS, ("Error writing message"));
  1595.             stop_io();
  1596.             return RP_BAD;
  1597.         }
  1598.     }
  1599.  
  1600.     return RP_OK;
  1601. }
  1602.  
  1603. /*   */
  1604.  
  1605. static char *parseSubject(file)
  1606. char    *file;
  1607. {
  1608.     char    buf[BUFSIZ], *ret = NULLCP, *ix;
  1609.     int    subject = FALSE, len;
  1610.     FILE    *fd;
  1611.     if ((fd = fopen(file, "r")) == NULL)
  1612.         return NULLCP;
  1613.  
  1614.     while (subject == FALSE
  1615.            && fgets(buf, BUFSIZ, fd) != NULLCP) {
  1616.         if ((ix = index(buf, ':')) != NULLCP) {
  1617.             *ix = '\0';
  1618.             if (lexequ("subject",buf) == 0) {
  1619.                 subject = TRUE;
  1620.                 ix++;
  1621.                 while (*ix && isspace(*ix)) ix++;
  1622.                 len = strlen(ix);
  1623.                 *(ix + len - 1) = '\0';
  1624.                 ret = strdup(ix);
  1625.             }
  1626.         }
  1627.     }
  1628.     (void) fclose(fd);
  1629.     return ret;
  1630. }
  1631.  
  1632. extern char    *hdr_822_bp; 
  1633.  
  1634. static int  isHdr(entry)
  1635. struct dirent *entry;
  1636. {
  1637.     if (strncmp(entry->d_name, hdr_822_bp, strlen(hdr_822_bp)) == 0)
  1638.         return 1;
  1639.     return 0;
  1640. }
  1641.  
  1642. static char *getSubject(msg_id, recip)
  1643. char    *msg_id;
  1644. ADDR    *recip;
  1645. {
  1646.     char    *dir = NULLCP, hdr[MAXPATHLENGTH], *subject = NULLCP;
  1647.     struct dirent **namelist = NULL;
  1648.     int    gothdr = FALSE,
  1649.         rcnt = recip->ad_rcnt;
  1650.     recip->ad_rcnt = 0;
  1651.     while (gothdr == FALSE && recip->ad_rcnt <= rcnt) { 
  1652.         if (qid2dir(msg_id, recip, TRUE, &dir) == OK) {
  1653.             if (_scandir(dir, &namelist, isHdr, NULLIFP) > 0)
  1654.                 gothdr = TRUE;
  1655.         }
  1656.         recip->ad_rcnt++;
  1657.     }
  1658.  
  1659.     recip->ad_rcnt = rcnt;
  1660.     if (gothdr == FALSE)
  1661.         return NULLCP;
  1662.     if ((*namelist)->d_name[0] != '/')
  1663.         (void) sprintf(hdr, "%s/%s", dir, (*namelist)->d_name);
  1664.     else
  1665.         (void) strcpy(hdr, (*namelist)->d_name);
  1666.  
  1667.     subject = parseSubject(hdr);
  1668.     free((char *) namelist);
  1669.     free(dir);
  1670.     return subject;
  1671. }
  1672.  
  1673.  
  1674. static int        get822Mailbox(ix, pmailbox)
  1675. Rrinfo    *ix;
  1676. char    **pmailbox;
  1677. {    
  1678.     ADDR    *ad;
  1679.     char    buf[BUFSIZ];
  1680.     *pmailbox = NULLCP;
  1681.     for (ad = PPQuePtr -> Raddress; ad; ad = ad->ad_next)
  1682.         if (ad -> ad_no == ix -> rr_recip)
  1683.             break;
  1684.     if (ad == NULL)
  1685.         (void) sprintf(buf,"recipient %d",
  1686.                    ix -> rr_recip);
  1687.     else if (ad -> ad_r822adr != NULL) {
  1688.         char    *str = NULLCP;
  1689.         ap_s2s (ad -> ad_r822adr, &str, order_pref);
  1690.         if (str != NULLCP && *str != '\0') {
  1691.             (void) sprintf(buf, "%s", str);
  1692.             free(str);
  1693.         } else
  1694.             (void) sprintf(buf, "%s", 
  1695.                        ad -> ad_r822adr);
  1696.     } else if (ad -> ad_value != NULL)
  1697.         (void) sprintf(buf, "%s", ad -> ad_value);
  1698.     else if (ad -> ad_type == AD_X400_TYPE
  1699.            && ad -> ad_r400adr != NULL)
  1700.         (void) sprintf(buf, "%s", ad -> ad_r400adr);
  1701.     else {
  1702.         PP_LOG (LLOG_EXCEPTIONS, ("Error no address string given for recip '%d'\n", ix -> rr_recip));
  1703.         return RP_BAD;
  1704.     }
  1705.     *pmailbox = strdup(buf);
  1706.     return RP_OK;
  1707. }
  1708.  
  1709. static int allSameType(ix, type)
  1710. Rrinfo    *ix;
  1711. int    type;
  1712. {
  1713.     if (ix == NULL) return FALSE;
  1714.     while (ix != NULL && ix->rr_report.rep_type == type)
  1715.         ix = ix -> rr_next;
  1716.     if (ix == NULL)
  1717.         return TRUE;
  1718.     else
  1719.         return FALSE;
  1720. }
  1721.  
  1722. static int allSameMta(ix, pmta)
  1723. Rrinfo    *ix;
  1724. char    **pmta;
  1725. {
  1726.     ADDR    *ad;
  1727.     int    first = TRUE, allSame = TRUE;
  1728.  
  1729.     
  1730.     while (ix != NULL) {
  1731.         for (ad = PPQuePtr -> Raddress; ad; ad = ad->ad_next)
  1732.             if (ad -> ad_no == ix -> rr_recip)
  1733.                 break;
  1734.         if (ad != NULL
  1735.             && ad -> ad_outchan != NULL
  1736.             && ad -> ad_outchan -> li_mta) {
  1737.             if (first == TRUE) {
  1738.                 *pmta = strdup(ad -> ad_outchan -> li_mta);
  1739.                 first = FALSE;
  1740.             } else if (lexequ(*pmta, ad -> ad_outchan -> li_mta) != 0)
  1741.                 allSame = FALSE;
  1742.         }
  1743.         ix = ix -> rr_next;
  1744.     }
  1745.     if (first == FALSE && allSame == TRUE)
  1746.         return TRUE;
  1747.     return FALSE;
  1748. }
  1749.